//
//  File Name   :   IFileSystem.cpp
//  Description :   IFileSystem implementation file.
//  Author      :   William McVicar
//  Mail        :   mcvicar.william@gmail.com
//

//  Precompiled Header
#include "CommonDefines.h"

//  Library Includes

//  Local Includes

//  This includes
#include "IFileSystem.h"

//  Macros

//  Static Variables
Protein::Directory Protein::IFileSystem::sm_HomeDirectory;
Protein::Directory Protein::IFileSystem::sm_WorkingDirectory;

#if defined( PROTEIN_PLATFORM_WINDOWS )
	const c8* Protein::IFileSystem::sm_szPathSeparator = "\\";
	const c16*Protein::IFileSystem::sm_wszPathSeparator = L"\\";
	#define PROTEIN_MAX_PATH MAX_PATH
#elif defined( PROTEIN_PLATFORM_IOS )
	const c8*  Protein::IFileSystem::sm_szPathSeparator = "/";
	const c16* Protein::IFileSystem::sm_wszPathSeparator = L"/";
	#define PROTEIN_MAX_PATH 260
#endif

//  Global Variables
const c8* g_kTEXT_READ_ONLY					= "r";
const c8* g_kTEXT_WRITE_ONLY				= "w";
const c8* g_kTEXT_APPEND					= "a";
const c8* g_kTEXT_READ_AND_WRITE			= "r+";
const c8* g_kTEXT_CREATE_READ_AND_WRITE		= "w+";
const c8* g_kTEXT_READ_AND_APPEND			= "a+";
const c8* g_kBINARY_READ_ONLY				= "rb";
const c8* g_kBINARY_WRITE_ONLY				= "wb";
const c8* g_kBINARY_APPEND					= "ab";
const c8* g_kBINARY_READ_AND_WRITE			= "r+b";
const c8* g_kBINARY_CREATE_READ_AND_WRITE	= "w+b";
const c8* g_kBINARY_READ_AND_APPEND			= "a+b";
const c8* g_kMIXED_READ_AND_WRITE			= "rb+";
const c8* g_kMIXED_CREATE_READ_AND_WRITE	= "wb+";
const c8* g_kMIXED_READ_AND_APPEND			= "ab+";

//  Static Function Prototypes

//  Implementation

namespace Protein
{

IFileSystem::IFileSystem()
{

}

IFileSystem::~IFileSystem()
{

}

void IFileSystem::AddSearchDirectory( const Directory& _krDirectory )
{
	m_FileSystemPaths.push_back( _krDirectory );
}

void IFileSystem::CreateSearchDirectory( const c16* _wzPath, bool _bAddRecursive )
{
	c8 buf[ PROTEIN_MAX_PATH ];
	wcstombs( buf, _wzPath, sizeof( c16 ) * PROTEIN_MAX_PATH );
	CreateSearchDirectory( buf, _bAddRecursive );
}

void IFileSystem::CreateSearchDirectory( const c8* _szPath, bool _bAddRecursive )
{
	Directory dir( _szPath );

	if( _bAddRecursive )
		dir.AddSubDirectoriesRecursive();

	m_FileSystemPaths.push_back( dir );
}

const Directory& IFileSystem::GetHomeDirectory() const
{
	return sm_HomeDirectory;
}

const Directory& IFileSystem::GetWorkingDirectory() const
{
	return sm_WorkingDirectory;
}

void IFileSystem::SetHomeDirectory( const c8* _szHomePath )
{
	sm_HomeDirectory.SetPath( _szHomePath );
}

void IFileSystem::SetWorkingDirectory( const c8* _szWorkingDirectory, bool _bRecursive )
{
	sm_WorkingDirectory.ClearSubdirectories();
	sm_WorkingDirectory.SetPath( _szWorkingDirectory );
	if( _bRecursive )
		sm_WorkingDirectory.AddSubDirectoriesRecursive();
}

void IFileSystem::SetWorkingDirectory( const Directory& _krWorkingDirectory )
{
	sm_WorkingDirectory = _krWorkingDirectory;
}

IFileSystem::eFILESYSTEM_ERROR IFileSystem::FileExists( const c8* _szFilename, std::string& _rFilepath, const Directory& _krDirectory, bool _bRecursive ) const
{
	c8 buf[ PROTEIN_MAX_PATH ];
	IFileSystem::eFILESYSTEM_ERROR error = FileExists( _szFilename, buf, _krDirectory, _bRecursive );
	if( error == IFileSystem::FILESYSTEM_ERROR_OK )
		_rFilepath.assign( buf );

	return error;
}

u32 IFileSystem::MakeFourCC( c8 _c0, c8 _c1, c8 _c2, c8 _c3 )
{
	return ( static_cast<u32>(_c0) << 0)  | (static_cast<u32>(_c1) << 8) |
			(static_cast<u32>(_c2) << 16) | (static_cast<u32>(_c3) << 24);
}

bool IFileSystem::IsEOF( FILE* _pFile )
{
	return ( feof(_pFile) != 0 );
}

}